#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/un.h>
#include <unistd.h>
#include <pthread.h>

#define err_log(errlog) do { perror(errlog); exit(1); } while (0)

#define N (128)

void *psend(void *a);
void *precv(void *a);

int main(int argc, char *argv[])
{
	pthread_t send, recv;

	if (pthread_create(&send, NULL, psend, NULL) == -1)
	{
		err_log("fail to create pthread send");
	}

	if (pthread_create(&recv, NULL, precv, NULL) == -1)
	{
		err_log("fail to create pthread recv");
	}

	void *result = NULL;

	if (pthread_join(send, &result) == -1) {
		err_log("fail to recollect send");
	}

	if (pthread_join(recv, &result) == -1) {
		err_log("fail to recollect recv");
	}

	return 0;	
}

void *psend(void *a)
{
	int sockfd;
	struct sockaddr_un serveraddr;
	struct sockaddr_un clientaddr;
	socklen_t addrlen = sizeof(clientaddr);
	char buf[N] = { 0 };

	if ((sockfd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
	{
		err_log("fail to socket");
	}

	serveraddr.sun_family = AF_UNIX;
	strcpy(serveraddr.sun_path, "/tmp/gsocket");
	while (1) 
	{
		bzero(buf, N);
		fgets(buf, N, stdin);
		buf[strlen(buf) - 1] = 0;

		if (sendto(sockfd, buf, N, 0, (const struct sockaddr *)&serveraddr, addrlen) < 0)
		{
			err_log("fail to sendto");
		}

		if (strncmp(buf, "quit", 4) == 0) 
		{
			break;
		}
	}
	close(sockfd);
}

void *precv(void *a)
{
	int sockfd;
	struct sockaddr_un serveraddr;
	struct sockaddr_un clientaddr;
	socklen_t addrlen = sizeof(clientaddr);
	char buf[N] = { 0 };

	if ((sockfd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
	{
		err_log("fail to socket");
	}

	serveraddr.sun_family = AF_UNIX;
	strcpy(serveraddr.sun_path, "/tmp/csocket");
	unlink("/tmp/csocket");

	if (bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
	{
		err_log("fail to bind");
	}

	while (1)
	{
		bzero(buf, N);
		if (recvfrom(sockfd, buf, N, 0, (struct sockaddr *)&clientaddr, &addrlen) < 0)
		{
			err_log("fail to recvfrom");
		}
		printf("recv: %s from %s\n", buf, clientaddr.sun_path);
		if (strncmp(buf, "quit", 4) == 0)
		{
			break;
		}
	}

	close(sockfd);
}
